package com.mac.common.util;
 
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import com.mac.common.constants.Constant;
import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Excel 工具类
 * @author macao
 *
 */
public class ExcelUtil {
	private static Logger log = LoggerFactory.getLogger(ExcelUtil.class);
 
	/**
	 * 导入Excel 数据处理 
	 * 
	 * @param 
	 * 			fileIn Excel文件流
	 * @param
	 * 			isCellType 是否需要进行列格式处理,true:是, false:否 (为false时，所有格式转为文本格式处理) 
	 * @return 
	 * 			List&lt;Map&lt;String, Object&gt;&gt; list集合 
	 * @throws 
	 * 			IOException 流处理异常
	 * @throws 
	 * 			BusinessException 业务异常
	 */
	@SuppressWarnings({ "deprecation", "resource" })
	public static List<Map<String, Object>> readExcel (InputStream fileIn, boolean isCellType) throws IOException, Exception {
		/**
		 * 返回读取的数据集合
		 */
		List<Map<String, Object>> lists = new ArrayList<Map<String, Object>>();
		/**
		 * 根据指定的文件输入流导入Excel从而产生Workbook对象  
		 */
		Workbook wb0 = new HSSFWorkbook(fileIn);
		/**
		 * 获取Excel文档中的第一个表单  
		 */
		Sheet sht0 = wb0.getSheetAt(0);
		/**
		 * 处理字段
		 */
		Row row0 = sht0.getRow(0);

		int rown = 0;
		int celln = 0;
		if(!row0.getZeroHeight()) {
			throw new BusinessException("模板不正确，请重新下载模板后在进行导入！");
		}
		for (Row row : sht0) {
			Map<String, Object> temp = new HashMap<String, Object>();
			/**
			 * 过滤表头和隐藏列
			 */
			if (row.getRowNum() == 0 || row.getRowNum() == 1) {
				continue;
			}
			/**
			 * 过滤空行
			 */
			if (null == row || (CheckRowNull(row) == 0)) {
				continue;
			}
			for (int i = 0; i < row.getLastCellNum(); i++) {
				try {
					if (row.getCell(i) == null) {
						celln ++;
						continue;
					}
					if (!isCellType) {
						row.getCell(i).setCellType(Cell.CELL_TYPE_STRING);
					}
					switch (row.getCell(i).getCellType()) {
						case Cell.CELL_TYPE_NUMERIC:
							if (HSSFDateUtil.isCellDateFormatted(row.getCell(i))) {
								Object date = HSSFDateUtil.getJavaDate(row.getCell(i).getNumericCellValue());
								temp.put(row0.getCell(celln).getStringCellValue().trim(), date);
								break;
							}
							temp.put(row0.getCell(celln).getStringCellValue().trim(), row.getCell(i).getNumericCellValue());
							break;
						case Cell.CELL_TYPE_STRING:
							temp.put(row0.getCell(celln).getStringCellValue().trim(), row.getCell(i).getStringCellValue());
							break;
						case Cell.CELL_TYPE_FORMULA:
							temp.put(row0.getCell(celln).getStringCellValue().trim(), row.getCell(i).getCellFormula());
							break;
						case Cell.CELL_TYPE_BOOLEAN:
							temp.put(row0.getCell(celln).getStringCellValue().trim(), row.getCell(i).getBooleanCellValue());
							break;

						case Cell.CELL_TYPE_BLANK:
							temp.put(row0.getCell(celln).getStringCellValue().trim(), "");
							break;

						default:
							break;
					}
					celln ++;
					
				} catch (Exception e) {
					log.error(getErrorColumn(row, celln));
				}
				
			}
			lists.add(temp);
			/**
			 * 清零 列计数
			 */
			celln = 0;
			rown ++;
		}
		
		if (null == lists || lists.size() == 0) {
			throw new BusinessException("模板内容为空,请检查模板！");
		}
		log.info("Row = " + rown + celln + "\tlist.size() = " + lists.size());
		return lists;
		
	}
 
	/**
	 * 导出Excel WithResponse
	 * 
	 * @param  sheetName 
	 * 					如果为空 则用默认名： yyyyMMddHHmmss
	 * @param  flag 
	 * 					单元格是否自动换行
	 * @param  len 
	 * 					列宽度，为 0 时用默认列宽2
	 * @param  fileName 
	 * 					保存的文件名 如果为空 则用默认名： yyyyMMddHHmmss.xls
	 * @param  column 
	 * 					需要导出的列字段，以逗号(半角)分割
	 * @param  columnTitle 
	 * 					表头显示的名称，以逗号(半角)分割
	 * @param  dataList  
	 * 					需要导出的数据
	 * @param  response
	 * 					响应请求
	 * @throws BusinessException  
	 * 					业务异常
	 * @throws IOException 
	 * 					流处理异常
	 */
	@SuppressWarnings("resource")
	public static void ExportExcelWithResponse (String sheetName, boolean flag, int len, String fileName,String column, String columnTitle,
			List<Map<String, Object>> dataList, HttpServletResponse response) throws Exception, IOException {
		/**
		 * 处理表头字段
		 */
		String[] titleArr = columnTitle.split(",");
		/**
		 * 处理字段
		 */
		String[] columnArr = column.split(",");
		/**
		 * 默认行宽 2
		 */
		if(len == 0) {
			len = 2;
		}
		if (StringUtil.isEmpty(sheetName)) {
			sheetName = dateFormat(new Date());
		}
		if (StringUtil.isEmpty(fileName)) {
			fileName = dateFormat(new Date());
		}
		
		if (titleArr.length > 0 && titleArr.length == columnArr.length) {
			/**
			 *  第一步，创建一个webbook，对应一个Excel文件
			 */
			HSSFWorkbook wb = new HSSFWorkbook();
			/**
			 *  第二步，在webbook中添加一个sheet,对应Excel文件中的sheet
			 */
			HSSFSheet sheet = wb.createSheet(sheetName);
			
			// sheet.setDefaultColumnWidth(15); //统一设置列宽
 
			/**
			 *  创建第1行 也就是表头
			 */
			HSSFRow row = sheet.createRow((int) 0);
			/**
			 *  设置表头高度
			 */
			row.setHeightInPoints(20);
			/**
			 *  第三步，创建表头单元格样式 以及表头的字体样式
			 */
			HSSFCellStyle style = wb.createCellStyle();
			/**
			 *  创建字体样式
			 */
			HSSFFont headerFont = (HSSFFont) wb.createFont(); 
			/**
			 * 设置自动换行
			 */
			style.setWrapText(flag);
			style = setTitleStyle(style, headerFont);
 
			/**
			 *  第四步，创建表头的列
			 */
			for (int i = 0; i < titleArr.length; i++) 
			{
				/**
				 * 设置列宽度
				 */
				sheet.setColumnWidth(i, titleArr[i].getBytes().length * len * 256);
				HSSFCell cell = row.createCell(i);
				cell.setCellValue(titleArr[i]);
				cell.setCellStyle(style);
			}
 
			/**
			 *  第五步，创建单元格，并设置值
			 */
			for (int i = 0; i < dataList.size(); i++) 
			{
				row = sheet.createRow((int) i + 1);
 
				/**
				 * 为数据内容设置特点新单元格样式 自动换行 上下居中左右也居中
				 */
				HSSFCellStyle columnStyle = wb.createCellStyle();
				/**
				 * 设置自动换行
				 */
				columnStyle.setWrapText(true);
				columnStyle = setColumnStyle(columnStyle, null);
				
				HSSFCell datacell = null;
				/**
				 * 初始化单元格
				 */
				for (int j = 0; j < titleArr.length; j++) 
				{
					Object o = dataList.get(i).get(columnArr[j]);
					datacell = row.createCell(j);
					datacell.setCellValue(String.valueOf(o != null ? o : ""));
					datacell.setCellStyle(columnStyle);
				}
			}
 
			/**
			 *  第六步，将文件存到浏览器设置的下载位置
			 */
			String filename = fileName + ".xls";
			response.setContentType("application/ms-excel;charset=UTF-8");
			response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(filename, "UTF-8"))));
			OutputStream out = response.getOutputStream();
			try {
				/**
				 *  将数据写出去
				 */
				wb.write(out);
				log.info("导出 {" + fileName + "} 成功！");
			} catch (Exception e) {
				log.error("导出 {" + fileName + "} 失败！");
				log.error("失败原因：" + e.getMessage());
				e.printStackTrace();
			} finally {
				out.close();
			}
		} else {
			log.info("没有选择需要导出的数据！");
			throw new BusinessException("没有选择需要导出的数据！");
		}
 
	}
	
	/**
	 * 下载Excel模板 
	 * 
	 * @param  sheetName 
	 * 					如果为空 则用默认名： yyyyMMddHHmmss
	 * @param  flag 
	 * 					单元格是否自动换行
	 * @param  len 
	 * 					列宽度，为 0 时用默认列宽2
	 * @param  fileName 
	 * 					保存的文件名 如果为空 则用默认名： yyyyMMddHHmmss.xls
	 * @param  columnTitle 
	 * 					表头显示的名称，以逗号(半角)分割
	 * @param
	 *  		column 要处理的字段名(大写,以逗号分割)
	 * @param  mapArr
	 * 		     		输入预制的数据,显示下拉框, 如果为空则不设置,Map&lt;Integer, String[]&gt;
	 * 					<br /> key为要设置数据的列下标(0开始),下拉框的值放到String[] 中。
	 * @param  rowN
	 * 					该列有rowN行进行数据有效性设置，rowN = 0  默认 500;
	 * @param  response
	 * 					响应请求
	 * 
	 * @throws Exception 
	 * 					异常
	 */
	@SuppressWarnings("resource")
	public static void downloadExcelModel (String sheetName, boolean flag, int len, String fileName, 
			String columnTitle, String column, Map<Integer, String[]> mapArr, int rowN, HttpServletResponse response) throws Exception {
		/**
		 * 处理表头字段
		 */
		String[] titleArr = columnTitle.split(",");
		/**
		 * 隐藏列
		 */
		String[] columnArr = column.toUpperCase().split(",");

		/**
		 * 默认行宽 2
		 */
		if(len == 0) {
			len = 2;
		}
		if(rowN == 0) {
			rowN = 500;
		}
		if (StringUtil.isEmpty(sheetName)) {
			sheetName = dateFormat(new Date());
		}
		if (StringUtil.isEmpty(fileName)) {
			fileName = dateFormat(new Date());
		}
		
		if (titleArr.length > 0) {
			/**
			 *  第一步，创建一个webbook，对应一个Excel文件
			 */
			HSSFWorkbook wb = new HSSFWorkbook();
			/**
			 *  第二步，在webbook中添加一个sheet,对应Excel文件中的sheet
			 */
			HSSFSheet sheet = wb.createSheet(sheetName);
			/**
			 *  创建第0行 也就是隐藏列字段
			 */
			HSSFRow row0 = sheet.createRow((int) 0);
			row0.setZeroHeight(true);
			/**
			 *  创建第1行 也就是表头
			 */
			HSSFRow row = sheet.createRow((int) 1);
			/**
			 *  设置表头高度
			 */
			row.setHeightInPoints(20);
			/**
			 *  第三步，创建表头单元格样式 以及表头的字体样式
			 */
			HSSFCellStyle style = wb.createCellStyle();
			/**
			 *  创建字体样式
			 */
			HSSFFont headerFont = (HSSFFont) wb.createFont(); 
			/**
			 * 设置自动换行
			 */
			style.setWrapText(flag);
			style = setTitleStyle(style, headerFont);
 
			/**
			 *  第四.一步，创建表头的列
			 */
			for (int i = 0; i < titleArr.length; i++) 
			{
				/**
				 * 设置输入预制的数据,显示下拉框
				 */
				if(null != mapArr) {
					if (mapArr.containsKey(i)) {
						sheet = setHSSFValidation(sheet, mapArr.get(i), 1, rowN, i, i);// 第一列的前501行都设置为选择列表形式.
						//sheet = setHSSFPrompt(sheet, "promt Title", "prompt Content",0, 500, 1, 1);// 第二列的前501行都设置提示.
					}
				}
				/**
				 * 设置列宽度
				 */
				sheet.setColumnWidth(i, titleArr[i].getBytes().length * len * 256);
				HSSFCell cell = row.createCell(i);
				cell.setCellValue(titleArr[i]);
				cell.setCellStyle(style);
				/**
				 * 设置隐藏列字段
				 */
				HSSFCell cell0 = row0.createCell(i);
				cell0.setCellValue(columnArr[i]);
			}
 
			/**
			 *  第六步，将文件存到浏览器设置的下载位置
			 */
			String filename = fileName + ".xls";
			response.setContentType("application/ms-excel;charset=UTF-8");
			response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(filename, "UTF-8"))));
			OutputStream out = response.getOutputStream();
			try {
				/**
				 *  将数据写出去
				 */
				wb.write(out);
				log.info("导出 {" + fileName + "} 成功！");
			} catch (Exception e) {
				log.error("导出 {" + fileName + "} 失败！");
				log.error("失败原因：" + e.getMessage());
				e.printStackTrace();
			} finally {
				out.close();
			}
		} else {
			log.info("没有选择需要导出的数据！");
			throw new Exception("没有选择需要导出的数据！");
		}
 
	}
	
	
	
 
	
	/**
	 * 实体类转换Map
	 * 
	 * @param obj 实体类对象
	 * @return Map 转换后的map
	 */
	public static Map<String, Object> beanToMap (Object obj){
        Map<String, Object> map =new HashMap<String, Object>();
        try {
        	/**
             * 获取所有私有属性
             */
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                String varName = field.getName();
                boolean accessFlag = field.isAccessible();
                field.setAccessible(true);
                Object data = field.get(obj);
                if(data != null){
                	data = dataFormat(data);
                    map.put(varName.toUpperCase(), String.valueOf(data).trim());
                }
               field.setAccessible(accessFlag);
            }
            
            return map;
        } catch (IllegalAccessException e) {  

            System.out.println("实例化 JavaBean 失败"); 
            e.printStackTrace();

        } catch (IllegalArgumentException e) {  
            System.out.println("映射错误"); 
            e.printStackTrace();

        } catch (Exception e) {
        	System.out.println("转换失败");  
        	e.printStackTrace();
        }
        
        return null;
    }
	
	
	/**
	 * 实体类转换Map 
	 * 
	 * @param obj 实体类
	 * @param maParam 需要转换显示值的参数MAP ,如果maParam为空则不进行字段值转换,
	 * 		  <br/> maParam&lt;key,map&lt;key1, value&gt;&gt;
	 * 		  <br/> key 为 字段名（大写），key1为字段值，value为字段显示的有效值 
	 * @return Map 转换后的map
	 */
	public static Map<String, Object> beanToMap (Object obj, Map<String, Map<String, Object>> maParam) {
		if (null == maParam || maParam.size() == 0) {
			return beanToMap(obj);
		}
		
		return beanToMapAddParam(obj, maParam);
	}
	
	/**
	 *  实体类转换Map 
	 *  
	 * @param obj 实体类
	 * @param maParam 需要转换显示值的参数MAP
	 * @return Map 转换后的map
	 */
	private static Map<String, Object> beanToMapAddParam (Object obj, Map<String, Map<String, Object>> maParam) {
		Map<String, Object> map =new HashMap<String, Object>();
        try {
        	/**
             * 获取所有私有属性
             */
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                String varName = field.getName();
                boolean accessFlag = field.isAccessible();
                field.setAccessible(true);
                Object data = field.get(obj);
                if(data != null){
                	data = dataFormat(data);
                	if (maParam.containsKey(varName.toUpperCase())) {
                		data = maParam.get(varName.toUpperCase()).get(data);
                	}
                		
                    map.put(varName.toUpperCase(), String.valueOf(data));
                }
               field.setAccessible(accessFlag);
            }
            
            return map;
        } catch (IllegalAccessException e) {  

            System.out.println("实例化 JavaBean 失败"); 
            e.printStackTrace();

        } catch (IllegalArgumentException e) {  
            System.out.println("映射错误"); 
            e.printStackTrace();

        } catch (Exception e) {
        	System.out.println("转换失败");  
        	e.printStackTrace();
        }
        
        return null;
    }
	
	
	 /** 

     * 将一个 Map 对象转化为一个 JavaBean 

     * @param clazz 要转化的类型 

     * @param map 包含属性值的 map 
     * 
     * @param maParam 需要转换值的map&lt;key,map&lt;key1,value&gt;&gt; 
     * 		  <br />key 为对应的字段 （大写）,key1 为 字段对应的显示值

     * @return JavaBean 对象 
     */  
	@SuppressWarnings("rawtypes")
	public static <T> T mapToBean(Class<T> clazz, Map map,  Map<String, Map<String, Object>> maParam) {  
		if (null == maParam || maParam.size() == 0) {
			 return mapToBean(clazz, map);
		}
		
		return mapToBeanAddParam(clazz, map, maParam);
	}
	
	
	/**
	 * 将一个 Map 对象转化为一个 JavaBean 
	 * @param clazz 要转化的类型 
	 *
     * @param map 包含属性值的 map 
     * 
	 * @return  JavaBean 对象 
	 */

    @SuppressWarnings("rawtypes")  
    public static <T> T mapToBean(Class<T> clazz, Map map) {  

        T obj = null;  

        try {  
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz);  
             // 创建 JavaBean 对象  
            obj = clazz.newInstance(); 

            // 给 JavaBean 对象的属性赋值  
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  

            for (int i = 0; i < propertyDescriptors.length; i++) {  

                PropertyDescriptor descriptor = propertyDescriptors[i];  

                String propertyName = descriptor.getName();
                if(StringUtil.isNotEmpty(propertyName)) {
                	propertyName = propertyName.toUpperCase();
                }

                if (map.containsKey(propertyName)) {  

                    // 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。  

                    Object value = map.get(propertyName);  

                    if (null == value) {  

                        value = null;  

                    } else {
                    	value = String.valueOf(value).trim();
                    }

                    Object[] args = new Object[1];  

                    try {  
                    	if(null != value) {
                    		args[0] = typeFormat(descriptor, value);
                    		
                    		descriptor.getWriteMethod().invoke(obj, args);  
                    	}

                    } catch (InvocationTargetException | ParseException e) {  
                        System.err.println("字段映射失败"); 
                        log.error("字段映射失败");
                        e.printStackTrace();
                    }  

                }  

            }  

        } catch (IllegalAccessException e) {  
            System.err.println("实例化 JavaBean 失败");
            log.error("实例化 JavaBean 失败");
            e.printStackTrace();
            
        } catch (IntrospectionException e) {  
            System.err.println("分析类属性失败"); 
            log.error("分析类属性失败");
            e.printStackTrace();
            
        } catch (IllegalArgumentException e) {  
            System.err.println("映射错误");
            log.error("映射错误");
            e.printStackTrace();
            
        } catch (InstantiationException e) {  
            System.err.println("实例化 JavaBean 失败"); 
            log.error("实例化 JavaBean 失败");
            e.printStackTrace();
        }  

        return (T) obj;  

    }  
    
    
    /** 

     * 将一个 Map 对象转化为一个 JavaBean 

     * @param clazz 要转化的类型 

     * @param map 包含属性值的 map 
     * 
     * @param maParam 需要转换值的map key 为对应的字段 （大写）

     * @return JavaBean 对象 
     */  

    @SuppressWarnings("rawtypes")  
    private static <T> T mapToBeanAddParam(Class<T> clazz, Map map, Map<String, Map<String, Object>> maParam) {  

        T obj = null;  

        try {  
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz);  
             // 创建 JavaBean 对象  
            obj = clazz.newInstance(); 

            // 给 JavaBean 对象的属性赋值  
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  

            for (int i = 0; i < propertyDescriptors.length; i++) {  

                PropertyDescriptor descriptor = propertyDescriptors[i];  

                String propertyName = descriptor.getName();
                if(StringUtil.isNotEmpty(propertyName)) {
                	propertyName = propertyName.toUpperCase();
                }

                if (map.containsKey(propertyName)) {  

                    // 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。  

                    Object value = map.get(propertyName);  

                    if (null == value) {  

                        value = null;  

                    } else {
                    	value = String.valueOf(value).trim();
                    }

                    Object[] args = new Object[1];  

                    try {  
                    	if (maParam.containsKey(propertyName)) {
                    		for (Object key : maParam.get(propertyName).keySet()) {
                    			if (String.valueOf(key).trim().equals(value)) {
                    				value = maParam.get(propertyName).get(value);
                    				break;
                    			}
                    		}
                    		
                    	}
                    	
                    	if(null != value) {
                    		args[0] = typeFormat(descriptor, value);
                    		
                    		descriptor.getWriteMethod().invoke(obj, args);  
                    	}

                    } catch (InvocationTargetException | ParseException e) {  
                        System.err.println("字段映射失败"); 
                        log.error("字段映射失败");
                        e.printStackTrace();
                    }  

                }  

            }  

        } catch (IllegalAccessException e) {  
            System.err.println("实例化 JavaBean 失败");
            log.error("实例化 JavaBean 失败");
            e.printStackTrace();
            
        } catch (IntrospectionException e) {  
            System.err.println("分析类属性失败"); 
            log.error("分析类属性失败");
            e.printStackTrace();
            
        } catch (IllegalArgumentException e) {  
            System.err.println("映射错误");
            log.error("映射错误");
            e.printStackTrace();
            
        } catch (InstantiationException e) {  
            System.err.println("实例化 JavaBean 失败"); 
            log.error("实例化 JavaBean 失败");
            e.printStackTrace();
        }  

        return (T) obj;  

    }  
    
    /**
     * 根据实体属性类型转换对应的属性值
     * 
     * @param descriptor 实体属性
     * @param value 要处理的数据 
     * @return Object 类型转换后的数据
     * @throws ParseException
     */
    private static Object typeFormat (PropertyDescriptor descriptor, Object value) throws ParseException {
    	if(null != value) {
    		if (descriptor.getPropertyType().equals(Date.class)) {
    			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    			value = sdf.parse(String.valueOf(value));
    			
    		} else if (descriptor.getPropertyType().equals(double.class) || descriptor.getPropertyType().equals(Double.class)) {
    			value = Double.parseDouble(String.valueOf(value));
    			
    		} else if (descriptor.getPropertyType().equals(BigDecimal.class)) {
    			value = new BigDecimal(String.valueOf(value));
    			
    		} else if (descriptor.getPropertyType().equals(Float.class) || descriptor.getPropertyType().equals(float.class)) {
    			value = Float.parseFloat(String.valueOf(value));
    			
    		} else if (descriptor.getPropertyType().equals(Integer.class) || descriptor.getPropertyType().equals(int.class)) {
    			value = Integer.parseInt(String.valueOf(value));
    			
    		} else if (descriptor.getPropertyType().equals(Boolean.class) || descriptor.getPropertyType().equals(boolean.class)) {
    			value = Boolean.parseBoolean(String.valueOf(value));
    			
    		} else if (descriptor.getPropertyType().equals(Long.class) || descriptor.getPropertyType().equals(long.class)) {
    			value = Long.parseLong(String.valueOf(value));
    			
    		}
    		
    	}
    	
    	return value;
    }


	/**
	 * 处理Excel导出日期格式
	 * 
	 * @param obj 数据格式处理
	 * @return String yyyy-MM-dd HH:mm:ss/yyyy-MM-dd
	 */
	private static String dataFormat (Object obj) {
		SimpleDateFormat format = new SimpleDateFormat(Constant.PATTERN_TIMESTAMP);
        String str = "";
        if (null != obj ) {
        	str = String.valueOf(obj);
        	if (obj instanceof Date) {
            	str = format.format(obj);
            	str = str.split("00:00:00")[0].trim();
            }
            if (obj instanceof BigDecimal) {
            	str = String.valueOf(obj);
            }
            if (obj instanceof Double) {
            	str = String.valueOf(obj);
            }
        }
        
        return str;
	}
	
	/**
	 * 格式化 日期 格式 yyyyMMddHHmmss
	 * @param date 日期
	 * @return String yyyyMMddHHmmss
	 */
	private static String dateFormat (Date date) {
		SimpleDateFormat format = new SimpleDateFormat(Constant.dateFormat);
        String str = null;
        if (null != date) {
        	str = format.format(date);
        }
        return str;
	}
	
	/**
	 * 判断行为空
	 * @param row Excel的行
	 * @return int 0:为空行 其他不为空
	 */

	@SuppressWarnings("deprecation")
	private static int CheckRowNull (Row row){
		int num = 0;
		Iterator<Cell> cellItr =row.iterator();
		while(cellItr.hasNext()){
		 Cell c =cellItr.next();                        
		 if(c.getCellType() != HSSFCell.CELL_TYPE_BLANK){
			 num++;
		 }
		}
		return num;
	
	}
	
	/**
	 * 设置表头样式
	 * 
	 * @param style 样式对象
	 * @param headerFont 字体设置对象
	 * @return HSSFCellStyle 样式对象
	 */
	@SuppressWarnings("deprecation")
	private static HSSFCellStyle setTitleStyle (HSSFCellStyle style, HSSFFont headerFont) {
		try {
			/**
			 * 创建一个上下居中格式
			 */
			style.setVerticalAlignment(VerticalAlignment.CENTER);
			/**
			 * 左居中
			 */
			style.setAlignment(HorizontalAlignment.CENTER);
			
			style.setBottomBorderColor(HSSFColor.BLACK.index);
			style.setBorderBottom(BorderStyle.THIN);
			style.setBorderLeft(BorderStyle.THIN);
			style.setBorderRight(BorderStyle.THIN);
			style.setBorderTop(BorderStyle.THIN);
			
			headerFont.setBold(true); // 字体加粗
			headerFont.setFontName("宋体"); // 设置字体类型
			headerFont.setFontHeightInPoints((short) 13); // 设置字体大小
			style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
			style.setFillForegroundColor(HSSFColor.LIGHT_TURQUOISE.index);
			style.setFont(headerFont); // 为标题样式设置字体样式
			
		} catch (Exception e) {
			log.error("Excel表头样式设置失败");
			e.printStackTrace();
		}
		
		return style;
	}
	
	
	/**
	 * 设置单元格样式
	 * 
	 * @param style 样式对象
	 * @param headerFont 字体设置对象
	 * @return HSSFCellStyle 样式对象
	 */
	@SuppressWarnings("deprecation")
	private static HSSFCellStyle setColumnStyle (HSSFCellStyle columnStyle, HSSFFont headerFont) {
		try {
			/**
			 * 创建一个上下居中格式
			 */
			columnStyle.setVerticalAlignment(VerticalAlignment.CENTER);
			/**
			 * 左居中
			 */
			columnStyle.setAlignment(HorizontalAlignment.CENTER);

			/**
			 * 设置边框
			 */
			columnStyle.setBottomBorderColor(HSSFColor.BLACK.index);
			columnStyle.setBorderBottom(BorderStyle.THIN);
			columnStyle.setBorderLeft(BorderStyle.THIN);
			columnStyle.setBorderRight(BorderStyle.THIN);
			columnStyle.setBorderTop(BorderStyle.THIN);
			
		} catch (Exception e) {
			log.error("Excel单元格样式设置失败");
			e.printStackTrace();
		}
		
		return columnStyle;
	}
	
	private static String getErrorColumn (Row row, int cell) {
		String str = "Excel文件第 " + (row.getRowNum()) + " 行, 第 " + (cell + 1)  + " 列  处理失败,请检查！";
		
		return str;
	}
	
	/**

	 * 设置某些列的值只能输入预制的数据,显示下拉框.

	 * @param sheet 要设置的sheet.

	 * @param textlist 下拉框显示的内容

	 * @param firstRow 开始行

	 * @param endRow 结束行

	 * @param firstCol   开始列

	 * @param endCol  结束列

	 * @return 设置好的sheet.

	 */

	public static HSSFSheet setHSSFValidation(HSSFSheet sheet,

			String[] textlist, int firstRow, int endRow, int firstCol,

			int endCol) {

		// 加载下拉列表内容

		DVConstraint constraint = DVConstraint.createExplicitListConstraint(textlist);

		// 设置数据有效性加载在哪个单元格上,四个参数分别是：起始行、终止行、起始列、终止列

		CellRangeAddressList regions = new CellRangeAddressList(firstRow,endRow, firstCol, endCol);

		// 数据有效性对象
		HSSFDataValidation data_validation_list = new HSSFDataValidation(regions, constraint);

		sheet.addValidationData(data_validation_list);

		return sheet;

	}
	
	
	/**

	 * 设置单元格上提示

	 * @param sheet  要设置的sheet.

	 * @param promptTitle 标题

	 * @param promptContent 内容

	 * @param firstRow 开始行

	 * @param endRow  结束行

	 * @param firstCol  开始列

	 * @param endCol  结束列

	 * @return 设置好的sheet.

	 */

	public static HSSFSheet setHSSFPrompt(HSSFSheet sheet, String promptTitle,

			String promptContent, int firstRow, int endRow ,int firstCol,int endCol) {

		// 构造constraint对象

		DVConstraint constraint = DVConstraint.createCustomFormulaConstraint("BB1");

		// 四个参数分别是：起始行、终止行、起始列、终止列

		CellRangeAddressList regions = new CellRangeAddressList(firstRow,endRow,firstCol, endCol);

		// 数据有效性对象
		HSSFDataValidation data_validation_view = new HSSFDataValidation(regions,constraint);

		data_validation_view.createPromptBox(promptTitle, promptContent);

		sheet.addValidationData(data_validation_view);

		return sheet;

	}
}
